package com.commerce.product.service.impl;

import com.commerce.product.constant.RedisConstant;
import com.commerce.product.service.AntiSpamService;
import com.commerce.product.utils.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;

/**
 * 防刷限流服务实现
 */
@Slf4j
@Service
public class AntiSpamServiceImpl implements AntiSpamService {

    @Autowired
    private RedisUtil redisUtil;

    @Override
    public boolean checkIpRateLimit(String ip) {
        try {
            String key = RedisConstant.buildIpRateLimitKey(ip);
            return redisUtil.checkRateLimit(key, 
                                          RedisConstant.RATE_LIMIT_WINDOW, 
                                          RedisConstant.IP_RATE_LIMIT_COUNT);
        } catch (Exception e) {
            log.error("IP限流检查失败: ip={}, error={}", ip, e.getMessage());
            // 异常时允许通过，避免影响正常用户
            return true;
        }
    }

    @Override
    public boolean checkUserRateLimit(Long userId) {
        try {
            String key = RedisConstant.buildUserRateLimitKey(userId);
            return redisUtil.checkRateLimit(key, 
                                          RedisConstant.RATE_LIMIT_WINDOW, 
                                          RedisConstant.USER_RATE_LIMIT_COUNT);
        } catch (Exception e) {
            log.error("用户限流检查失败: userId={}, error={}", userId, e.getMessage());
            // 异常时允许通过，避免影响正常用户
            return true;
        }
    }

    @Override
    public boolean isUserBlacklisted(Long userId) {
        try {
            String key = RedisConstant.buildSuspiciousUserKey(userId);
            return redisUtil.exists(key);
        } catch (Exception e) {
            log.error("检查用户黑名单失败: userId={}, error={}", userId, e.getMessage());
            return false;
        }
    }

    @Override
    public boolean isIpBlacklisted(String ip) {
        try {
            String key = RedisConstant.buildSuspiciousIpKey(ip);
            return redisUtil.exists(key);
        } catch (Exception e) {
            log.error("检查IP黑名单失败: ip={}, error={}", ip, e.getMessage());
            return false;
        }
    }

    @Override
    public void recordUserBehavior(Long userId, String ip, String action, String userAgent) {
        try {
            String key = RedisConstant.buildUserBehaviorKey(userId);
            
            // 构建行为记录
            Map<String, Object> behavior = new HashMap<>();
            behavior.put("ip", ip);
            behavior.put("action", action);
            behavior.put("userAgent", userAgent);
            behavior.put("timestamp", System.currentTimeMillis());
            behavior.put("time", LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
            
            // 使用有序集合存储，按时间戳排序
            long score = System.currentTimeMillis();
            redisUtil.set(key + ":" + score, behavior, RedisConstant.BEHAVIOR_ANALYSIS_WINDOW);
            
            log.debug("记录用户行为: userId={}, ip={}, action={}", userId, ip, action);
            
        } catch (Exception e) {
            log.error("记录用户行为失败: userId={}, ip={}, action={}, error={}", 
                     userId, ip, action, e.getMessage());
        }
    }

    @Override
    public boolean analyzeSuspiciousBehavior(Long userId, String ip) {
        try {
            // 检查用户在短时间内的行为频率
            String userKey = RedisConstant.buildUserBehaviorKey(userId);
            
            // 统计最近5分钟内的行为次数
            long currentTime = System.currentTimeMillis();
            long windowStart = currentTime - RedisConstant.BEHAVIOR_ANALYSIS_WINDOW * 1000;
            
            // 简化实现：检查用户在短时间内的请求频率
            String frequencyKey = "behavior:frequency:" + userId;
            Long requestCount = redisUtil.increment(frequencyKey, 1, 300); // 5分钟窗口
            
            // 如果5分钟内请求超过50次，认为可疑
            if (requestCount != null && requestCount > 50) {
                log.warn("检测到可疑行为: userId={}, ip={}, 5分钟内请求{}次", userId, ip, requestCount);
                return true;
            }
            
            // 检查是否来自多个不同IP（账号共享检测）
            String ipKey = "behavior:ip:" + userId;
            redisUtil.set(ipKey + ":" + ip, "1", 3600); // 1小时内记录IP
            
            // 这里可以添加更复杂的行为分析逻辑
            // 例如：检查用户代理变化、请求模式等
            
            return false;
            
        } catch (Exception e) {
            log.error("分析可疑行为失败: userId={}, ip={}, error={}", userId, ip, e.getMessage());
            return false;
        }
    }

    @Override
    public void addUserToBlacklist(Long userId, String reason, long duration) {
        try {
            String key = RedisConstant.buildSuspiciousUserKey(userId);
            
            Map<String, Object> blacklistInfo = new HashMap<>();
            blacklistInfo.put("reason", reason);
            blacklistInfo.put("addTime", LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
            blacklistInfo.put("duration", duration);
            
            redisUtil.set(key, blacklistInfo, duration);
            
            log.warn("用户已加入黑名单: userId={}, reason={}, duration={}秒", userId, reason, duration);
            
        } catch (Exception e) {
            log.error("添加用户到黑名单失败: userId={}, reason={}, error={}", userId, reason, e.getMessage());
        }
    }

    @Override
    public void addIpToBlacklist(String ip, String reason, long duration) {
        try {
            String key = RedisConstant.buildSuspiciousIpKey(ip);
            
            Map<String, Object> blacklistInfo = new HashMap<>();
            blacklistInfo.put("reason", reason);
            blacklistInfo.put("addTime", LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
            blacklistInfo.put("duration", duration);
            
            redisUtil.set(key, blacklistInfo, duration);
            
            log.warn("IP已加入黑名单: ip={}, reason={}, duration={}秒", ip, reason, duration);
            
        } catch (Exception e) {
            log.error("添加IP到黑名单失败: ip={}, reason={}, error={}", ip, reason, e.getMessage());
        }
    }

    @Override
    public void removeUserFromBlacklist(Long userId) {
        try {
            String key = RedisConstant.buildSuspiciousUserKey(userId);
            redisUtil.delete(key);
            log.info("用户已从黑名单移除: userId={}", userId);
        } catch (Exception e) {
            log.error("从黑名单移除用户失败: userId={}, error={}", userId, e.getMessage());
        }
    }

    @Override
    public void removeIpFromBlacklist(String ip) {
        try {
            String key = RedisConstant.buildSuspiciousIpKey(ip);
            redisUtil.delete(key);
            log.info("IP已从黑名单移除: ip={}", ip);
        } catch (Exception e) {
            log.error("从黑名单移除IP失败: ip={}, error={}", ip, e.getMessage());
        }
    }

    @Override
    public AntiSpamResult comprehensiveCheck(Long userId, String ip, String userAgent) {
        try {
            // 1. 检查黑名单
            if (isUserBlacklisted(userId)) {
                return new AntiSpamResult(false, "用户已被封禁");
            }
            
            if (isIpBlacklisted(ip)) {
                return new AntiSpamResult(false, "IP已被封禁");
            }
            
            // 2. 检查限流
            if (!checkIpRateLimit(ip)) {
                return new AntiSpamResult(false, "IP访问频率过高，请稍后再试");
            }
            
            if (!checkUserRateLimit(userId)) {
                return new AntiSpamResult(false, "用户访问频率过高，请稍后再试");
            }
            
            // 3. 记录行为
            recordUserBehavior(userId, ip, "flash_sale_request", userAgent);
            
            // 4. 分析可疑行为
            if (analyzeSuspiciousBehavior(userId, ip)) {
                // 发现可疑行为，临时限制
                addUserToBlacklist(userId, "可疑行为检测", 3600); // 封禁1小时
                return new AntiSpamResult(false, "检测到异常行为，账号已被临时限制");
            }
            
            return new AntiSpamResult(true, "检查通过");
            
        } catch (Exception e) {
            log.error("综合防刷检查失败: userId={}, ip={}, error={}", userId, ip, e.getMessage());
            // 异常时允许通过，避免影响正常用户
            return new AntiSpamResult(true, "检查异常，允许通过");
        }
    }
}
